package labox.innovation.gameserver.model;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javolution.util.FastList;
import labox.innovation.config.Config;
import labox.innovation.gameserver.model.actor.L2Attackable;
import labox.innovation.gameserver.model.actor.L2Character;
import labox.innovation.gameserver.model.actor.L2Playable;
import labox.innovation.gameserver.model.actor.L2Summon;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance; //import labox.innovation.gameserver.model.actor.instance.L2SiegeFlagInstance;
import labox.innovation.gameserver.model.actor.instance.L2SummonInstance; //import labox.innovation.gameserver.model.entity.TvTEvent;
import labox.innovation.gameserver.network.SystemMessageId;
import labox.innovation.gameserver.network.serverpackets.SystemMessage;
import labox.innovation.gameserver.skills.Env;
import labox.innovation.gameserver.skills.Formulas;
import labox.innovation.gameserver.skills.conditions.Condition;
import labox.innovation.gameserver.skills.funcs.AttributeStringSplice;
import labox.innovation.gameserver.skills.funcs.Func;
import labox.innovation.gameserver.skills.funcs.FuncTemplate;
import labox.innovation.gameserver.templates.StatsSet;
import labox.innovation.gameserver.templates.effects.EffectTemplate;
import labox.innovation.gameserver.templates.item.L2WeaponType;
import labox.innovation.gameserver.templates.skills.L2SkillType;
import labox.innovation.gameserver.util.Util;

/**
 * 技能基类 version1.0 2010 1.6
 * 
 * @version $Revision: 1.3.2.8.2.22 $ $Date: 2005/04/06 16:13:42 $
 */
public abstract class L2Skill implements IChanceSkillTrigger {
	protected static final Logger _log = LoggerFactory.getLogger(L2Skill.class.getName());

	private static final L2Object[] _emptyTargetList = new L2Object[0];

	public static final int SKILL_LUCKY = 194;

	public static final int SKILL_CREATE_COMMON = 1320;

	public static final int SKILL_CREATE_DWARVEN = 172;

	public static final int SKILL_CRYSTALLIZE = 248;

	public static final int SKILL_DIVINE_INSPIRATION = 1405;

	public static final int SKILL_CLAN_LUCK = 390;

	public static final boolean geoEnabled = Config.GEODATA > 0;

	//技能的施放类型
	//主动，被动，开关型
	public static enum SkillOpType {
		OP_PASSIVE, OP_ACTIVE
	}

	/** Target types of skills : SELF, PARTY, CLAN, PET... */
	public static enum SkillTargetType {
		/**
		 * 没目标
		 */
		TARGET_NONE,
		/**
		 * 目标是自己
		 */
		TARGET_SELF,
		/**
		 * 目标是一个
		 */
		TARGET_ONE,
		/**
		 * 目标是一个队伍
		 */
		TARGET_PARTY,
		/**
		 * 目标是队伍成员
		 */
		TARGET_PARTY_MEMBER,

		/**
		 * 目标是其他队伍
		 */
		TARGET_PARTY_OTHER,

		/**
		 * 目标是地面
		 */
		TARGET_GROUND,

		/**
		 * 目标是前方区域
		 */
		TARGET_FRONT_AREA,

		/**
		 * 目标是大群
		 */
		TARGET_MULTIFACE,

		/**
		 * 目标是宠物
		 */
		TARGET_PET,

		/**
		 * 目标是召唤兽
		 */
		TARGET_SUMMON,

		/**
		 * 目标是敌对召唤兽
		 */
		TARGET_ENEMY_SUMMON,

		/**
		 * 目标是自己的宠物
		 */
		TARGET_OWNER_PET,

		//下面的都可以删除

		/**
		 * 目标是一片区域
		 */
		TARGET_AREA,

		/**
		 * 目标是后方区域
		 */
		TARGET_BEHIND_AREA,

	}

	/**
	 * 物品id 哪个物品 带有的技能
	 */
	public int _itemid = -1;

	//conditional values
	public final static int COND_RUNNING = 0x0001;

	public final static int COND_WALKING = 0x0002;

	public final static int COND_SIT = 0x0004;

	public final static int COND_BEHIND = 0x0008;

	public final static int COND_CRIT = 0x0010;

	public final static int COND_LOWHP = 0x0020;

	public final static int COND_ROBES = 0x0040;

	public final static int COND_CHARGES = 0x0080;

	public final static int COND_SHIELD = 0x0100;

	//人宠合一状态
	public final static int COND_COMPOSE_PLAYER_PET = 0x0200;

	private static final Func[] _emptyFunctionSet = new Func[0];

	private static final L2Effect[] _emptyEffectSet = new L2Effect[0];

	// these two build the primary key
	// 技能id 和 等级
	private final int _id;

	private final int _level;

	//技能最高等级
	private final int _skill_max_lv;

	//技能可学等级
	private final int _skill_learn_lv;

	//技能描述
	private final String _skill_description;

	//技能名
	private final String _name;

	//技能操作类型
	private final SkillOpType _operateType;

	/**
	 * 以下为技能施放时的消耗
	 */
	//mp, hp消耗
	private final int _mpConsume;

	private final int _hpConsume;

	//自身物品消耗
	private final int[] _self_item_consume_id;

	private final int[] _self_item_consume_num;

	//目标物品消耗
	private final int[] _target_item_consume_id;

	private final int[] _target_item_consume_num;

	//消耗当前功勋值
	private final int _meritConsume;

	//消耗荣誉值
	private final int _honorConsume;

	//下面3个字段 可能要移到其他技能中去 不是有所技能都消耗物品的
	//持续消耗的物品id
	private final int[] _itemConsumeIdOT;

	//持续消耗的物品数
	private final int[] _itemConsumeOT;

	//消耗物品周期
	private final int _itemConsumeSteps;

	/**
	 * 技能施放时的消耗 结束
	 */

	/**
	 * 以下为技能施放的条件 TODO: 后面 全部需要转到condition中去
	 */

	//是否要装备某个武器
	private final int _needWeaponId;

	//是否装备某类武器
	private final int _needWeaponType;

	//是否是队长
	private final boolean _isTeamleader;

	//最小的气血值
	private final int _minHp;

	/**
	 * 技能施放的条件 结束
	 */

	//技能分类(用于区别技能的归属性。无特殊用途)
	private final int _skillClass;

	//技能类型(伤害 和 影响的状态类型)
	private final L2SkillType _skillType;

	//技能目标类型
	private final SkillTargetType _targetType;

	//公共CD的影响类型. 为 -1的话 不受公共CD的影响
	private int _startCoolTimeCategory;

	//技能公共冷却时间
	private final int _coolTime;

	//技能冷却类型
	//通过这个字段， 影响某一类技能的冷却时间
	//此类型相同的的技能 理论上  _categoryReuseTime 都是一样的
	private int _category;

	//技能类别冷却时间
	private int _categoryReuseTime;

	//技能在使用时间
	private final int _reuseDelay;

	//	//技能 在装备上的延迟使用时间
	//	//当一个技能在装备上时 ，装上装备后 需要冷却的时间
	//	private final int _equipDelay;
	//技能仇恨值
	private final int _aggroPoints;

	// Effecting area of the skill, in radius.
	// The radius center varies according to the _targetType:
	// "caster" if targetType = AURA/PARTY/CLAN or "target" if targetType = AREA
	//技能半径
	private final int _skillRadius;

	//技能施放的距离
	private final int _castRange;

	//效果作用范围
	private final int _effectRange;

	/**
	 * 技能动画id
	 */

	//技能释放效果动画
	private final int _dispersion_skill_action_cartoon_id;

	//技能释放动作动画ID
	private final int _dispersion_action_cartoon_id;

	//技能效果动画ID
	private final int _dispersion_effect_cartoon_id;

	//技能飞行动画ID
	private final int _skill_fly_cartoon_id;

	//技能命中效果动画ID
	private final int _skill_hit_effect_id;

	//技能图标ID
	private final int _skill_icon_id;

	//技能效果动画类型
	private final int _effectIdType; //  1持续性动画 0非持续性动画

	/**
	 * 技能动画id 结束
	 */

	/**
	 * 触发技能相关 (被动触发)
	 */
	//触发的技能id
	private final int _triggeredId;

	//触发的技能等级
	private final int _triggeredLevel;

	//触发的技能类型
	private final String _chanceType;

	//触发条件
	protected ChanceCondition _chanceCondition = null;

	/**
	 * 触发技能相关 结束
	 */

	/**
	 * 特殊状态
	 */

	//忽视物理防御
	private final boolean _ignorePDef;

	//忽视魔法防御
	private final boolean _ignoreMDef;

	//	//忽视金属性抗性
	//	private final int _ignore_gold_def;
	//	//忽视木属性抗性
	//	private final int _ignore_wood_def;
	//	//忽视水属性抗性
	//	private final int _ignore_water_def;
	//	//忽视火属性抗性
	//	private final int _ignore_fire_def;
	//	//忽视土属性抗性
	//	private final int _ignore_soil_def;
	//忽视闪避
	private final boolean _ignoreEvasion;

	//能否被反射
	private final boolean _canBeReflected;

	//能否被驱散
	private final boolean _canBeDispeled;

	//是否是进攻型技能
	private final boolean _isOffensive;

	//死亡后 是否仍存在
	private final boolean _stayAfterDeath; // skill should stay after death

	//是否是 魔法
	private final boolean _magic;

	//是否是药水技能
	private final boolean _isPotion;

	//魔法等级
	private final int _magicLevel;

	//是否是Debuff
	private final boolean _isDebuff;

	private final boolean _isBuff;

	//是否中性魔法
	private final boolean _isNeutral;

	/**
	 * 特殊状态 结束
	 */

	/**
	 * 技能条件 和 效果模板
	 */

	//技能施放条件
	//下面2个条件在检测的时候 只用使用一个
	//itemPreCondition 表示需要装备武器道具的条件
	protected Condition _preCondition;

	protected Condition _itemPreCondition;

	protected FuncTemplate[] _funcTemplates;

	protected EffectTemplate[] _effectTemplates;

	protected EffectTemplate[] _effectTemplatesSelf;

	// base success chance
	//技能威力

	/**
	 * 技能条件 和 效果模板 结束
	 */

	//驱散debuff的最大数量
	protected final int _maxNegatedEffects;

	/**
	 * 技能伤害
	 */

	//技能威力
	private final double _power;

	//技能百分比伤害
	private final double _percentPower;

	/**
	 * 技能伤害 结束
	 */

	//保存 物品模板的属性值
	public Map<Integer, Integer> _attributs = new HashMap<Integer, Integer>();

	//技能属性描述
	public StringBuilder _skillAttributeDescription = new StringBuilder();

	protected String _skillAttributeDes = null;

	protected L2Skill(StatsSet set) {
		////
		_id = set.getInteger("skill_id");
		_level = set.getInteger("level");

		_name = set.getString("name");
		_operateType = set.getEnum("operateType", SkillOpType.class);
		_magic = set.getBool("isMagic", false);

		_mpConsume = set.getInteger("mpConsume", 0);

		_hpConsume = set.getInteger("hpConsume", 0);

		_category = set.getInteger("categoryCool", -1);

		_castRange = set.getInteger("castRange", -1);
		_effectRange = set.getInteger("effectRange", -1);

		_stayAfterDeath = set.getBool("stayAfterDeath", false);

		_coolTime = set.getInteger("coolTime", 0);
		_isDebuff = set.getBool("isDebuff", false);
		_isBuff = set.getBool("isBuff", false);

		_isPotion = set.getBool("isPotion", false);

		_reuseDelay = set.getInteger("reuseDelay", 0);

		_maxNegatedEffects = set.getInteger("maxNegatedEffects", 0);

		//		_equipDelay = set.getInteger("equipDelay", 0);

		_skillRadius = set.getInteger("skillRadius", 80);

		_isNeutral = set.getBool("neutral", false);

		_targetType = set.getEnum("targetType", SkillTargetType.class);
		//绝对值伤害
		// percentPower %比伤害 待增加
		_power = set.getFloat("absolutePower", 0.f);
		_percentPower = set.getFloat("percentPower", 0.f) / 100;
		_magicLevel = set.getInteger("magicLvl", 1);

		_skillType = set.getEnum("skillType", L2SkillType.class);
		//		//附加效果类型. 附加类型为NEGATE  那么这个技能同时能取消某些技能效果
		//		_effectType = set.getEnum("effectType", L2SkillType.class, null);

		//		_condition = set.getInteger("condition", 0);

		_isOffensive = set.getBool("offensive", isSkillTypeOffensive());

		_triggeredId = set.getInteger("triggeredId", 0);
		_triggeredLevel = set.getInteger("triggeredLevel", 0);
		_chanceType = set.getString("chanceType", "");
		if (_chanceType != "" && !_chanceType.isEmpty())
			_chanceCondition = ChanceCondition.parse(set);

		_aggroPoints = set.getInteger("aggroPoints", 0);

		//		_flyType = set.getString("flyType", null);
		//		_flyRadius = set.getInteger("flyRadius", 200);
		//		_flyCourse = set.getFloat("flyCourse", 0);
		_canBeReflected = set.getBool("canBeReflected", false);

		_canBeDispeled = set.getBool("canBeDispeled", false);

		//以下是新增加的字段
		_skill_fly_cartoon_id = set.getInteger("flyCartoonId", -1);
		_skill_hit_effect_id = set.getInteger("hitEffectId", -1);
		_skill_icon_id = set.getInteger("iconId", -1);
		_dispersion_action_cartoon_id = set.getInteger("actionCartoonID", -1);

		_dispersion_skill_action_cartoon_id = set.getInteger("skillActionCartoonID", -1);
		_dispersion_effect_cartoon_id = set.getInteger("effectCartoonId", -1);
		_effectIdType = set.getInteger("effectIdType", 0);
		_target_item_consume_id = set.getIntegerArray("tItemConsumeId", null);
		_target_item_consume_num = set.getIntegerArray("tItemConsumeNum", null);
		_self_item_consume_id = set.getIntegerArray("sItemConsumeId", null);
		_self_item_consume_num = set.getIntegerArray("sItemConsumeNum", null);

		_ignorePDef = set.getBool("ignorePDef", false);
		_ignoreMDef = set.getBool("ignoreMDef", false);

		//消耗当前功勋值
		_meritConsume = set.getInteger("meritConsume", 0);

		_itemConsumeIdOT = set.getIntegerArray("itemConsumeId", null);
		_itemConsumeOT = set.getIntegerArray("itemConsumeOT", null);
		_itemConsumeSteps = set.getInteger("itemConsumeSteps", -1);

		_skill_learn_lv = set.getInteger("learnLvl", 1);
		_skill_max_lv = set.getInteger("maxLvl", 1);
		_skill_description = set.getString("description", null);
		//技能分类
		_skillClass = set.getInteger("skillClass", -1);

		_ignoreEvasion = set.getBool("ignoreEvasion", false);

		_honorConsume = set.getInteger("honorConsume", 0);

		_minHp = set.getInteger("minHp", -1);
		_needWeaponId = set.getInteger("weaponId", 0);
		L2WeaponType wp = set.getEnum("weaponType", L2WeaponType.class);
		if (wp != null)
			_needWeaponType = wp.ordinal();
		else
			_needWeaponType = -1;
		_isTeamleader = set.getBool("isLeader", false);

		//冷却
		//公共冷却类型
		_startCoolTimeCategory = set.getInteger("coolTimeCategory", -1);
		//类型冷却类型
		_categoryReuseTime = set.getInteger("categoryReuseTime", -1);

	}

	public abstract void useSkill(L2Character caster, L2Object[] targets);

	public final L2SkillType getSkillType() {
		return _skillType;
	}

	public final boolean isDebuff() {
		return _isDebuff;
	}

	public final boolean isBuff() {
		return _isBuff;
	}

	/**
	 * Return the target type of the skill : SELF, PARTY, CLAN, PET...<BR>
	 * <BR>
	 * 
	 */
	//返回技能类型
	public final SkillTargetType getTargetType() {
		return _targetType;
	}

	/**
	 * Return the power of the skill.<BR>
	 * <BR>
	 * 返回技能威力 后面 可能需要具体 公式去修正.比如:不同的技能类型 需要不同的技能威力伤害公式等. 目前直接返回 技能威力 power
	 */
	public final double getPower(L2Character activeChar) {
		if (activeChar == null)
			return _power;

		int atk = 0;
		switch (_skillType) {
		//如果是 魔法 或 物理攻击
		//最终技能的 伤害为 角色本身的 物理 或 魔法攻击力 * %比伤害 + 技能绝对值伤害
		case PDAM:
			atk = activeChar.getPAtk();
			break;
		case MDAM:
			atk = activeChar.getMAtk();
			break;
		}

		return atk + atk * _percentPower + _power;

	}// end 

	/**
	 * Return the power of the skill.<BR>
	 * <BR>
	 * 返回技能威力
	 */
	public final double getPower() {
		return _power;
	}

	public final double getPersentPower() {
		return _percentPower;
	}

	/**
	 * 返回 魔法等级
	 * 
	 * @return
	 */
	public final int getMagicLevel() {
		return _magicLevel;
	}

	//忽略物理防御
	public final boolean ignorePhyDef() {
		return _ignorePDef;
	}

	public final boolean ignoreMagDef() {
		return _ignoreMDef;
	}

	//	public final boolean ignoreGoldDef()
	//	{
	//		return _ignore_gold_def;
	//	}
	//	
	//	public final int ignoreWoodDef()
	//	{
	//		return _ignore_wood_def;
	//	}
	//	
	//	public final int ignoreWaterDef()
	//	{
	//		return _ignore_water_def;
	//	}
	//	
	//	public final int ignoreFireDef()
	//	{
	//		return _ignore_fire_def;
	//	}
	//	
	//	public final int ignoreSoilDef()
	//	{
	//		return _ignore_soil_def;
	//	}

	public final boolean ignoreEvasion() {
		return _ignoreEvasion;
	}

	/**
	 * @return Returns the castRange. 返回技能施法距离
	 */
	public final int getCastRange() {
		return _castRange;
	}

	/**
	 * @return 返回技能带来的效果的范围.
	 */
	public final int getEffectRange() {
		return _effectRange;
	}

	/**
	 * @return Returns the hpConsume. 返回hp消耗
	 */
	public final int getHpConsume() {
		return _hpConsume;
	}

	/**
	 * @return Returns the id. 返回技能id
	 */
	public final int getId() {
		return _id;
	}

	//触发技能id 、等级
	public int getTriggeredId() {
		return _triggeredId;
	}

	public int getTriggeredLevel() {
		return _triggeredLevel;
	}

	//是否有触发技能
	public boolean triggerAnotherSkill() {
		return _triggeredId > 1;
	}

	/**
	 * @return Returns the _targetConsumeId. 返回目标消耗物品id
	 */
	public final int[] getTargetConsumeId() {
		return _target_item_consume_id;
	}

	public final int[] getTargetConsumeNum() {
		return _target_item_consume_num;
	}

	/**
	 * @return Returns the itemConsume. 返回自己消耗的物品
	 */
	public final int[] getItemConsume() {
		return _self_item_consume_num;
	}

	/**
	 * @return Returns the itemConsumeId.
	 */
	public final int[] getItemConsumeId() {
		return _self_item_consume_id;
	}

	/**
	 * @return Returns the level. 返回技能等级
	 */
	public final int getLevel() {
		return _level;
	}

	/**
	 * @return Returns the mpConsume. 返回mp消耗
	 */
	public final int getMpConsume() {
		return _mpConsume;
	}

	/**
	 * @return Returns the name. 返回技能名
	 */
	public final String getName() {
		return _name;
	}

	/**
	 * @return Returns the reuseDelay. 返回技能在使用时间
	 */
	public final int getReuseDelay() {
		//返回技能类型 冷却和 技能在使用时间 最大的一个
		return _reuseDelay;
	}

	/**
	 * @return Returns the coolTime. 返回技能公共冷却时间
	 */
	public final int getCoolTime() {
		return _coolTime;
	}

	/**
	 * 获得技能的冷却类型 通过这个字段， 影响某一类技能的冷却时间 此类型相同的的技能 理论上 _categoryReuseTime 都是一样的
	 * 
	 * @return
	 */
	public int getSkillCategory() {
		return _category;
	}

	/**
	 * 获得技能的类型冷却时间
	 * 
	 * @return
	 */
	public int getSkillCategoryReuseTime() {
		return _categoryReuseTime;
	}

	/**
	 * 获得技能的公共冷却类型 公共CD的影响类型. 为 -1的话 不受公共CD的影响
	 * 
	 * @return
	 */
	public int getStartCoolTimeCategory() {
		return _startCoolTimeCategory;
	}

	/**
	 * 返回技能的冷却类型
	 * 
	 * @return -1 表示类型不存在
	 */
	public final int getCategoryCoolTime() {
		return -1;
	}

	//	/**
	//	 * 返回技能 在装备上的延迟使用时间
	//	 * @return
	//	 */
	//	public final int getEquipDelay()
	//	{
	//		return _equipDelay;
	//	}

	/**
	 * 返回此技能的施法半径
	 * 
	 * @return
	 */
	public final int getSkillRadius() {
		return _skillRadius;
	}

	/**
	 * //是否是主动型技能
	 */
	public final boolean isActive() {
		return _operateType == SkillOpType.OP_ACTIVE;
	}

	/**
	 * //是否被动型技能
	 */
	public final boolean isPassive() {
		return _operateType == SkillOpType.OP_PASSIVE;
	}

	//	//是否开关型技能, 先不用 ，注释掉
	//	public final boolean isToggle() 
	//	{
	//		return _operateType == SkillOpType.OP_TOGGLE;
	//	}

	// 技能是否是被动触发型技能
	// 只有是被动技能，且触发条件存在的情况下 这个技能才是触发性技能
	public final boolean isChance() {
		return _chanceCondition != null && isPassive();
	}

	//返回触发型技能条件
	public ChanceCondition getChanceCondition() {
		return _chanceCondition;
	}

	/**
	 * 返回仇恨值
	 * 
	 * @return
	 */
	public final int getAggroPoints() {
		return _aggroPoints;
	}

	//返回需要武器的id
	//为 -1 或 0表不需要。 还没定
	public final int getWeaponsAllowed() {
		return _needWeaponId;
	}

	//返回需要武器的类
	//为 -1 或 0表不需要。 还没定
	public final int getWeaponTypeAllowed() {
		return _needWeaponType;
	}

	//是否需要队长
	public final boolean getIsTeamLeamLeader() {
		return _isTeamleader;
	}

	//返回技能需要的min_hp
	//当前气血值小于某个值
	public final int getMinHp() {
		return _minHp;
	}

	//pvp技能类型的判断
	//还需要修改 没定
	public final boolean isPvpSkill() {
		switch (_skillType) {
		case DOT:
		case BLEED:
		case CONFUSION:
		case POISON:
		case DEBUFF:
		case AGGDEBUFF:
		case STUN:
		case ROOT:
		case FEAR:
		case SLEEP:
		case MDOT:
		case MUTE:
		case CANCEL:
		case AGGDAMAGE:
		case STEAL_BUFF:
		case AGGREDUCE_CHAR:
		case MANADAM:
			return true;
		default:
			return false;
		}
	}

	/**
	 * 是否进攻型技能
	 * 
	 * @return
	 */
	public final boolean isOffensive() {
		return _isOffensive;
	}

	//是否是 进攻类型的技能
	public final boolean isSkillTypeOffensive() {
		switch (_skillType) {
		case PDAM:
		case MDAM:
		case DOT:
		case BLEED:
		case POISON:
		case AGGDAMAGE:
		case DEBUFF:
		case AGGDEBUFF:
		case STUN:
		case ROOT:
		case CONFUSION:
		case FATAL:
		case FEAR:
		case SLEEP:
		case MANADAM:
		case MDOT:
		case MUTE:
		case MANA_BY_LEVEL:
		case AGGREDUCE:
		case CANCEL:
		case AGGREMOVE:
		case AGGREDUCE_CHAR:
		case STEAL_BUFF:
			return true;
		default:
			return false;
		}
	}

	/**
	 * 死亡后是否有效
	 * 
	 * @return
	 */
	public final boolean isStayAfterDeath() {
		return _stayAfterDeath;
	}

	//	int weapons[] = {L2Weapon.WEAPON_TYPE_ETC, L2Weapon.WEAPON_TYPE_BOW,
	//	L2Weapon.WEAPON_TYPE_POLE, L2Weapon.WEAPON_TYPE_DUALFIST,
	//	L2Weapon.WEAPON_TYPE_DUAL, L2Weapon.WEAPON_TYPE_BLUNT,
	//	L2Weapon.WEAPON_TYPE_SWORD, L2Weapon.WEAPON_TYPE_DAGGER};
	//检查武器
	public final boolean getWeaponDependancy(L2Character activeChar) {
		if (getWeaponDependancy(activeChar, false)) {
			return true;
		} else {
			SystemMessage message = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED);
			message.addSkillName(this);
			activeChar.sendPacket(message);

			return false;
		}
	}

	public final boolean getWeaponDependancy(L2Character activeChar, boolean chance) {
		int weaponsAllowed = getWeaponsAllowed();
		//check to see if skill has a weapon dependency.
		if (weaponsAllowed == 0)
			return true;

		int mask = 0;

		if (activeChar.getActiveWeaponItem() != null)
			mask |= activeChar.getActiveWeaponItem().getItemType().mask();
		if (activeChar.getSecondaryWeaponItem() != null)
			mask |= activeChar.getSecondaryWeaponItem().getItemType().mask();

		if ((mask & weaponsAllowed) != 0)
			return true;

		return false;
	}

	//技能施法检查
	//需要修改流程
	/**
	 * 技能释放条件检查
	 * 
	 */
	public boolean checkCondition(L2Character activeChar, L2Object target, boolean itemOrWeapon) {
		if (activeChar.isGM() && !Config.GM_SKILL_RESTRICTION)
			return true;

		Condition preCondition = _preCondition;
		if (itemOrWeapon)
			preCondition = _itemPreCondition;
		if (preCondition == null)
			return true;

		Env env = new Env();
		env.player = activeChar;
		if (target instanceof L2Character) // TODO: object or char?
			env.target = (L2Character) target;
		env.skill = this;

		if (!preCondition.test(env)) {
			String msg = preCondition.getMessage();
			int msgId = preCondition.getMessageId();
			if (msgId != 0) {
				SystemMessage sm = new SystemMessage(msgId);
				activeChar.sendPacket(sm);
			} else if (msg != null) {
				activeChar.sendMessage(msg);
			}
			return false;
		}

		return checkCondition(activeChar);
	}

	/**
	 * 检查技能的其他限制条件
	 * 
	 * @param activeChar
	 * @return
	 */
	public boolean checkCondition(L2Character activeChar) {
		//气血限制
		if (_minHp > 0 && _minHp > activeChar.getCurrentHp()) {
			return false;
		}

		//队长限制
		if (_isTeamleader && activeChar.getParty() != null && activeChar.getParty().getPartyLeaderOID() != activeChar.getObjectId()) {
			return false;
		}

		return true;
	}

	//获得目标链
	//需要修改
	public final L2Object[] getTargetList(L2Character activeChar, boolean onlyFirst) {
		// Init to null the target of the skill
		L2Character target = null;

		// Get the L2Objcet targeted by the user of the skill at this moment
		L2Object objTarget = activeChar.getTarget();
		// If the L2Object targeted is a L2Character, it becomes the L2Character target
		if (objTarget instanceof L2Character) {
			target = (L2Character) objTarget;
		}

		return getTargetList(activeChar, onlyFirst, target);
	}

	/**
	 * Return all targets of the skill in a table in function a the skill type.<BR>
	 * <BR>
	 * 
	 * <B><U> Values of skill type</U> :</B><BR>
	 * <BR>
	 * <li>ONE : The skill can only be used on the L2PcInstance targeted, or on the caster if it's a L2PcInstance and no L2PcInstance targeted</li> <li>SELF</li> <li>HOLY, UNDEAD</li> <li>PET</li> <li>AURA, AURA_CLOSE</li> <li>AREA</li> <li>MULTIFACE</li> <li>PARTY, CLAN</li> <li>CORPSE_PLAYER, CORPSE_MOB, CORPSE_CLAN</li> <li>UNLOCKABLE</li> <li>ITEM</li><BR>
	 * <BR>
	 * 
	 * @param activeChar
	 *            The L2Character who use the skill 获得目标链 需要修改
	 * 
	 */
	public final L2Object[] getTargetList(L2Character activeChar, boolean onlyFirst, L2Character target) {
		List<L2Character> targetList = new FastList<L2Character>();

		// Get the target type of the skill
		// (ex : ONE, SELF, HOLY, PET, AURA, AURA_CLOSE, AREA, MULTIFACE, PARTY, CLAN, CORPSE_PLAYER, CORPSE_MOB, CORPSE_CLAN, UNLOCKABLE, ITEM, UNDEAD)
		//技能的释放类型
		//单个, 自己， 或团体等
		SkillTargetType targetType = getTargetType();

		// Get the type of the skill
		// (ex : PDAM, MDAM, DOT, BLEED, POISON, HEAL, HOT, MANAHEAL, MANARECHARGE, AGGDAMAGE, BUFF, DEBUFF, STUN, ROOT, RESURRECT, PASSIVE...)
		//技能类型
		L2SkillType skillType = getSkillType();

		switch (targetType) {
		// The skill can only be used on the L2Character targeted, or on the caster itself
		case TARGET_ONE: {
			boolean canTargetSelf = false;
			switch (skillType) {
			case BUFF:
			case HEAL:
			case HOT:
			case HEAL_PERCENT:
			case MANARECHARGE:
			case MANAHEAL:
			case NEGATE:
			case CANCEL:
			case CANCEL_DEBUFF:
			case REFLECT:
			case COMBATPOINTHEAL:
			case BALANCE_LIFE:
				canTargetSelf = true;
				break;
			}

			// Check for null target or any other invalid target
			if (target == null || target.isDead() || (target == activeChar && !canTargetSelf)) {
				//				System.out.println("目标为空 或 死亡 :" + target.isDead());
				activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
				return _emptyTargetList;
			}

			// If a target is found, return it in a table else send a system message TARGET_IS_INCORRECT
			return new L2Character[] { target };
		}
		case TARGET_SELF:
		case TARGET_GROUND: {
			return new L2Character[] { activeChar };
		}
		case TARGET_PET: {
			target = activeChar.getPet();
			if (target != null && !target.isDead())
				return new L2Character[] { target };

			return _emptyTargetList;
		}
		case TARGET_SUMMON: {
			target = activeChar.getPet();
			if (target != null && !target.isDead() && target instanceof L2SummonInstance)
				return new L2Character[] { target };

			return _emptyTargetList;
		}
		case TARGET_OWNER_PET: {
			if (activeChar instanceof L2Summon) {
				target = ((L2Summon) activeChar).getOwner();
				if (target != null && !target.isDead())
					return new L2Character[] { target };
			}

			return _emptyTargetList;
		}

			//片伤 
		case TARGET_AREA:
		case TARGET_FRONT_AREA:
		case TARGET_BEHIND_AREA: {
			if ((!(target instanceof L2Attackable || target instanceof L2Playable)) || // Target
					// is
					// not
					// L2Attackable
					// or
					// L2PlayableInstance
					(getCastRange() >= 0 && (target == null || target == activeChar))) // target
			// is
			// null
			// or
			// self
			// or
			// dead/faking
			{
				activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
				return _emptyTargetList;
			}

			final L2Character origin;
			final boolean srcInArena = (activeChar.isInsideZone(L2Character.ZONE_PVP) && !activeChar.isInsideZone(L2Character.ZONE_SIEGE));
			final int radius = getSkillRadius();

			if (getCastRange() >= 0) {
				if (!checkForAreaOffensiveSkills(activeChar, target, this, srcInArena))
					return _emptyTargetList;

				if (onlyFirst)
					return new L2Character[] { target };

				origin = target;
				targetList.add(origin); // Add target to target list
			} else
				origin = activeChar;

			final Collection<L2Character> objs = target.getKnownList().getKnownCharacters().values();
			//synchronized (activeChar.getKnownList().getKnownObjects())
			{
				for (L2Character obj : objs) {
					if (!(obj instanceof L2Attackable || obj instanceof L2Playable))
						continue;

					if (obj == origin)
						continue;

					if (Util.checkIfInRange(radius, origin, obj)) {

						if (!checkForAreaOffensiveSkills(activeChar, obj, this, srcInArena))
							continue;

						targetList.add(obj);
					}
				}
			}

			if (targetList.isEmpty())
				return _emptyTargetList;

			return targetList.toArray(new L2Character[targetList.size()]);
		}
			//360°全范围伤害
		case TARGET_MULTIFACE: {
			if ((!(target instanceof L2Attackable) && !(target instanceof FuzePcInstance))) {
				activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
				return _emptyTargetList;
			}

			if (!onlyFirst)
				targetList.add(target);
			else
				return new L2Character[] { target };

			final int radius = getSkillRadius();

			final Collection<L2Character> objs = target.getKnownList().getKnownCharactersInRadius(radius);
			//synchronized (activeChar.getKnownList().getKnownObjects())
			{
				for (L2Character obj : objs) {
					//					if (obj instanceof L2Attackable && obj != target)   //只对非玩家起效
					//						targetList.add(obj);
					if (obj.getObjectId() != activeChar.getObjectId() && obj != target && obj.isAutoAttackable(activeChar)) {
						targetList.add(obj);
					}

					if (targetList.isEmpty()) {
						activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_CANT_FOUND));
						return _emptyTargetList;
					}
				}
			}
			return targetList.toArray(new L2Character[targetList.size()]);
			//TODO multiface targets all around right now.  need it to just get targets
			//the character is facing.
		}
		case TARGET_PARTY: {
			if (onlyFirst)
				return new L2Character[] { activeChar };

			targetList.add(activeChar);

			final int radius = getSkillRadius();

			FuzePcInstance player = activeChar.getActingPlayer();
			if (activeChar instanceof L2Summon) {
				if (addCharacter(activeChar, player, radius, false))
					targetList.add(player);
			} else if (activeChar instanceof FuzePcInstance) {
				if (addSummon(activeChar, player, radius, false))
					targetList.add(player.getPet());
			}

			if (activeChar.isInParty()) {
				// Get a list of Party Members
				for (FuzePcInstance partyMember : activeChar.getParty().getPartyMembers()) {
					if (partyMember == null || partyMember == player)
						continue;

					if (addCharacter(activeChar, partyMember, radius, false))
						targetList.add(partyMember);

					if (addSummon(activeChar, partyMember, radius, false))
						targetList.add(partyMember.getPet());
				}
			}
			return targetList.toArray(new L2Character[targetList.size()]);
		}
		case TARGET_PARTY_MEMBER: {
			if ((target != null && target == activeChar) || (target != null && activeChar.isInParty() && target.isInParty() && activeChar.getParty().getPartyLeaderOID() == target.getParty().getPartyLeaderOID()) || (target != null && activeChar instanceof FuzePcInstance && target instanceof L2Summon && activeChar.getPet() == target) || (target != null && activeChar instanceof L2Summon && target instanceof FuzePcInstance && activeChar == target.getPet())) {
				if (!target.isDead()) {
					// If a target is found, return it in a table else send a system message TARGET_IS_INCORRECT
					return new L2Character[] { target };
				} else
					return _emptyTargetList;
			} else {
				activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
				return _emptyTargetList;
			}
		}
		case TARGET_PARTY_OTHER: {
			if (target != null && target != activeChar && activeChar.isInParty() && target.isInParty() && activeChar.getParty().getPartyLeaderOID() == target.getParty().getPartyLeaderOID()) {
				if (!target.isDead()) {
					if (target instanceof FuzePcInstance) {
						switch (getId()) {
						// FORCE BUFFS may cancel here but there should be a proper condition
						case 426:
							if (!((FuzePcInstance) target).isMageClass())
								return new L2Character[] { target };
							else
								return _emptyTargetList;
						case 427:
							if (((FuzePcInstance) target).isMageClass())
								return new L2Character[] { target };
							else
								return _emptyTargetList;
						}
					}
					return new L2Character[] { target };
				} else
					return _emptyTargetList;
			} else {
				activeChar.sendPacket(new SystemMessage(SystemMessageId.TARGET_IS_INCORRECT));
				return _emptyTargetList;
			}
		}
		case TARGET_ENEMY_SUMMON: {
			if (target instanceof L2Summon) {
				L2Summon targetSummon = (L2Summon) target;
				if (activeChar instanceof FuzePcInstance && activeChar.getPet() != targetSummon && !targetSummon.isDead() && (targetSummon.getOwner().getPvpFlag() != 0 || targetSummon.getOwner().getKarma() > 0) || (targetSummon.getOwner().isInsideZone(L2Character.ZONE_PVP) && ((FuzePcInstance) activeChar).isInsideZone(L2Character.ZONE_PVP)))
					return new L2Character[] { targetSummon };
			}
			return _emptyTargetList;
		}
		default: {
			activeChar.sendMessage("技能目标类型不正确");
			return _emptyTargetList;
		}
		}//end switch
	}

	//获得目标链
	//需要修改
	public final L2Object[] getTargetList(L2Character activeChar) {
		return getTargetList(activeChar, false);
	}

	//获得目标链
	//需要修改
	public final L2Object getFirstOfTargetList(L2Character activeChar) {
		L2Object[] targets;

		targets = getTargetList(activeChar, true);

		if (targets.length == 0)
			return null;
		else
			return targets[0];
	}

	/*
	 * Check if should be target added to the target list
	 * false if target is dead, target same as caster,
	 * target inside peace zone, target in the same party with caster,
	 * caster can see target
	 * Additional checks if not in PvP zones (arena, siege):
	 * target in not the same clan and alliance with caster,
	 * and usual skill PvP check.
	 * If TvT event is active - performing additional checks.
	 * 
	 * Caution: distance is not checked.
	 */
	//检查 目标是否可以 加入到目标列表中
	//需要修改
	public static final boolean checkForAreaOffensiveSkills(L2Character caster, L2Character target, L2Skill skill, boolean sourceInArena) {
		if (target == null || target.isDead() || target == caster)
			return false;

		final FuzePcInstance player = caster.getActingPlayer();
		if (player != null) {
			final FuzePcInstance targetPlayer = target.getActingPlayer();
			if (targetPlayer != null) {
				if (targetPlayer == caster || targetPlayer == player)
					return false;

				if (target.isInsideZone(L2Character.ZONE_PEACE))
					return false;

				if ((player.isInParty() && targetPlayer.isInParty()) && player.getParty().getPartyLeaderOID() == targetPlayer.getParty().getPartyLeaderOID())
					return false;

				//				if (!TvTEvent.checkForTvTSkill(player, targetPlayer, skill))
				//					return false;

				if (!sourceInArena && !(targetPlayer.isInsideZone(L2Character.ZONE_PVP) && !targetPlayer.isInsideZone(L2Character.ZONE_SIEGE))) {
					//					if (player.getAllyId() != 0 && player.getAllyId() == targetPlayer.getAllyId())
					//						return false;

					if (player.getClanId() != 0 && player.getClanId() == targetPlayer.getClanId())
						return false;

					if (!player.checkPvpSkill(targetPlayer, skill))
						return false;
				}
			}
		} else {
			// source is not playable
			if (!(target instanceof L2Playable))
				return false;
		}

		//		if (geoEnabled && !GeoData.getInstance().canSeeTarget(caster, target))
		//			return false;

		return true;
	}

	public static final boolean addSummon(L2Character caster, FuzePcInstance owner, int radius, boolean isDead) {
		final L2Summon summon = owner.getPet();

		if (summon == null)
			return false;

		return addCharacter(caster, summon, radius, isDead);
	}

	public static final boolean addCharacter(L2Character caster, L2Character target, int radius, boolean isDead) {
		if (isDead != target.isDead())
			return false;

		if (radius > 0 && !Util.checkIfInRange(radius, caster, target))
			return false;

		return true;

	}

	/**
	 * 技能相关计算函数 状态
	 * 
	 * @param effect
	 * @param player
	 * @return
	 */
	public final Func[] getStatFuncs(L2Effect effect, L2Character player) {
		if (!(player instanceof L2Playable) && !(player instanceof L2Attackable))
			return _emptyFunctionSet;

		if (_funcTemplates == null)
			return _emptyFunctionSet;

		List<Func> funcs = new FastList<Func>();

		for (FuncTemplate t : _funcTemplates) {
			Env env = new Env();
			env.player = player;
			env.skill = this;
			Func f = t.getFunc(env, this); // skill is owner
			if (f != null)
				funcs.add(f);
		}
		if (funcs.isEmpty())
			return _emptyFunctionSet;

		return funcs.toArray(new Func[funcs.size()]);
	}

	//是否带有效果
	public boolean hasEffects() {
		return (_effectTemplates != null && _effectTemplates.length > 0);
	}

	//获得效果模板
	public EffectTemplate[] getEffectTemplates() {
		return _effectTemplates;
	}

	/**
	 * Env is used to pass parameters for secondary effects (shield and ss/bss/bsss)
	 * 
	 * @return an array with the effects that have been added to effector
	 */
	/***
	 * 获得和此技能相关的效果 返回的效果列表 都是已schedule的effect ，如果这个效果成功释放的话
	 */
	public final L2Effect[] getEffects(L2Character effector, L2Character effected, Env env) {
		if (isPassive())
			return _emptyEffectSet;

		if (_effectTemplates == null)
			return _emptyEffectSet;

		// doors and siege flags cannot receive any effects
		// 门 和 siege flags 不受任何效果的影响
		//		if (effected instanceof L2DoorInstance || effected instanceof L2SiegeFlagInstance)
		//			return _emptyEffectSet;

		if (effector != effected) {
			if (effected.isInvul())
				return _emptyEffectSet;

			//如果技能是伤害性技能， 或 这是debuff， 且释放者是GM
			if ((isOffensive() || isDebuff()) && effector instanceof FuzePcInstance && ((FuzePcInstance) effector).isGM()) {
				//如果不能释放伤害 那么不会产生任何效果
				if (!((FuzePcInstance) effector).getAccessLevel().canGiveDamage())
					return _emptyEffectSet;
			}
		}

		List<L2Effect> effects = new FastList<L2Effect>();

		if (env == null)
			env = new Env();

		env.player = effector;
		env.target = effected;
		env.skill = this;

		for (EffectTemplate et : _effectTemplates) {
			boolean success = true;

			//效果释放是否成功
			if (et.effectPower > -1)
				success = Formulas.calcEffectSuccess(effector, effected, et, this);

			if (success) {
				L2Effect e = et.getEffect(env);
				if (e != null) {
					//处理效果
					//这个地方 效果将会被创建
					//					System.out.println("技能触发的效果，开始触发:" + e);
					e.scheduleEffect();
					effects.add(e);
				}
			} else if (effector instanceof FuzePcInstance) {
				SystemMessage sm = new SystemMessage(SystemMessageId.C1_RESISTED_YOUR_S2);
				sm.addCharName(effected);
				sm.addSkillName(this);
				((FuzePcInstance) effector).sendPacket(sm);
			}
		}

		if (effects.isEmpty())
			return _emptyEffectSet;

		return effects.toArray(new L2Effect[effects.size()]);
	}

	/**
	 * Warning: this method doesn't consider modifier (shield, ss, sps, bss) for secondary effects
	 * 
	 */
	public final L2Effect[] getEffects(L2Character effector, L2Character effected) {
		return getEffects(effector, effected, null);
	}

	public final L2Effect[] getEffectsSelf(L2Character effector) {
		if (isPassive())
			return _emptyEffectSet;

		if (_effectTemplatesSelf == null)
			return _emptyEffectSet;

		List<L2Effect> effects = new FastList<L2Effect>();

		for (EffectTemplate et : _effectTemplatesSelf) {
			Env env = new Env();
			env.player = effector;
			env.target = effector;
			env.skill = this;
			L2Effect e = et.getEffect(env);
			if (e != null) {
				e.scheduleEffect();
				effects.add(e);
			}
		}
		if (effects.isEmpty())
			return _emptyEffectSet;

		return effects.toArray(new L2Effect[effects.size()]);
	}

	public final void attach(FuncTemplate f) {
		if (_funcTemplates == null) {
			_funcTemplates = new FuncTemplate[] { f };
		} else {
			int len = _funcTemplates.length;
			FuncTemplate[] tmp = new FuncTemplate[len + 1];
			System.arraycopy(_funcTemplates, 0, tmp, 0, len);
			tmp[len] = f;
			_funcTemplates = tmp;
		}
	}

	public final void attach(EffectTemplate effect) {
		if (_effectTemplates == null) {
			_effectTemplates = new EffectTemplate[] { effect };
		} else {
			int len = _effectTemplates.length;
			EffectTemplate[] tmp = new EffectTemplate[len + 1];
			System.arraycopy(_effectTemplates, 0, tmp, 0, len);
			tmp[len] = effect;
			_effectTemplates = tmp;
		}

	}

	public final void attachSelf(EffectTemplate effect) {
		if (_effectTemplatesSelf == null) {
			_effectTemplatesSelf = new EffectTemplate[] { effect };
		} else {
			int len = _effectTemplatesSelf.length;
			EffectTemplate[] tmp = new EffectTemplate[len + 1];
			System.arraycopy(_effectTemplatesSelf, 0, tmp, 0, len);
			tmp[len] = effect;
			_effectTemplatesSelf = tmp;
		}
	}

	public final void attach(Condition c, boolean itemOrWeapon) {
		//如果是物品 或 武器限制条件。
		if (itemOrWeapon)
			_itemPreCondition = c;
		else
			_preCondition = c;
	}

	@Override
	public String toString() {
		return "" + _name + "[id=" + _id + ",lvl=" + _level + "]";
	}

	@Override
	public boolean triggersChanceSkill() {
		return _triggeredId > 0 && isChance();
	}

	@Override
	public int getTriggeredChanceId() {
		return _triggeredId;
	}

	@Override
	public int getTriggeredChanceLevel() {
		return _triggeredLevel;
	}

	@Override
	//获得触发条件
	public ChanceCondition getTriggeredChanceCondition() {
		return _chanceCondition;
	}

	public final boolean isMagic() {
		return _magic;
	}

	public final boolean isPotion() {
		return _isPotion;
	}

	//能否被反射
	public boolean canBeReflected() {
		return _canBeReflected;
	}

	//能否被驱散
	public boolean canBeDispeled() {
		return _canBeDispeled;
	}

	/**
	 * 返回技能描述
	 * 
	 * @return
	 */
	public String getDescription() {
		return _skill_description;
	}

	/**
	 * 获得技能最高学习低级
	 * 
	 * @return
	 */
	public int getSkillLearnMaxLvl() {
		return _skill_max_lv;
	}

	/**
	 * 获得可学技能等级
	 * 
	 * @return
	 */
	public int getSkillLearnLvl() {
		return _skill_learn_lv;
	}

	/**
	 * 获得技能锁消耗的 功勋值
	 * 
	 * @return
	 */
	public int getMeritConsume() {
		return _meritConsume;
	}

	/**
	 * 获得技能锁消耗的 荣誉值
	 * 
	 * @return
	 */
	public int getHonorConsume() {
		return _honorConsume;
	}

	/**
	 * 获得技能的持续消耗物品
	 * 
	 * @return
	 */
	public int[] getitemConsumeIdOT() {
		return _itemConsumeIdOT;
	}

	/**
	 * 获得 技能的持续消耗物品数
	 * 
	 * @return
	 */
	public int[] getitemConsumeNumOT() {
		return _itemConsumeOT;
	}

	/**
	 * 获得技能消耗的 物品周期
	 * 
	 * @return
	 */
	public int getitemConsumeSteps() {
		return _itemConsumeSteps;
	}

	/**
	 * 获得技能的分类
	 * 
	 * @return
	 */
	public int getSkillClass() {
		return _skillClass;
	}

	/**
	 * 获得技能的 系列图标
	 * 
	 * @return
	 */
	public int getActionCartoonId() {
		return _dispersion_action_cartoon_id;
	}

	/**
	 * 获得技能效果动画
	 * 
	 * @return
	 */
	public int getEffectCartoonId() {
		return _dispersion_effect_cartoon_id;
	}

	/**
	 * 获得技能释放效果动画
	 * 
	 * @return
	 */
	public int getSkillActionCartoonId() {
		return _dispersion_skill_action_cartoon_id;
	}

	/**
	 * 获得效果动画类型
	 * 
	 * @return
	 */
	public int getEffectIdType() {
		return _effectIdType;
	}

	public int getFlyCartoonId() {
		return _skill_fly_cartoon_id;
	}

	public int getHitCartoonId() {
		return _skill_hit_effect_id;
	}

	public int getIconId() {
		return _skill_icon_id;
	}

	public final boolean isNeutral() {
		return _isNeutral;
	}

	/**
	 * 获得技能 驱散debuff的最大数量
	 * 
	 * @return
	 */
	public final int getMaxNegatedEffects() {
		return _maxNegatedEffects;
	}

	/**
	 * 被取消的效果状态 通过技能的stats来确定效果
	 * 
	 * @return
	 */
	public final L2SkillType[] getNegateStats() {
		//TODO:
		//字段 待添加
		return null;
	}

	/**
	 * 如果以下2个字段， 存在， 那么 主动触发的技能 将替换掉 本技能 对目标做成的伤害 或 效果 都将是 主动触发技能上的 详见 Continuous 技能逻辑
	 */
	/**
	 * 获得技能主动 触发的技能 一般用于buff型 或 持续性的技能类型上
	 * 
	 * @return
	 */
	public final int getEffectId() {
		return 0;
	}

	/**
	 * 获得主动触发技能的等级
	 * 
	 * @return
	 */
	public final int getEffectLvl() {
		return 0;
	}

	/**
	 * 拼接技能描述。 这个函数 一般不被直接调用， 应该调用 getSkillAttributeDes 这个函数 会每次生成新的描述
	 * 
	 * @return
	 */
	public void getSkillDes(L2SkillLearn learn) {
		if (_skillAttributeDes == null) {
			_skillAttributeDes = "";
			;
		}
		_skillDesWithoutLearnCondition = _skillAttributeDes.intern();
		_skillAttributeDes += AttributeStringSplice.getInstance().getLearnSkillAttributeString(this, learn);
	}

	/**
	 * 没有学习条件的技能描述
	 */
	private String _skillDesWithoutLearnCondition;

	/**
	 * 拼接技能描述。 这个函数 不应该由外部使用技能的对象调用， 应该调用 getSkillAttributeDes 这个函数 会每次生成新的描述
	 * 
	 * @return
	 */
	public void getSkillDes() {
		_skillAttributeDes = AttributeStringSplice.getInstance().getAttributeString(this);
	}

	/**
	 * 获得 技能属性描述 字段
	 * 
	 * @return
	 */
	public String getSkillAttributeDes() {
		if (_skillAttributeDes == null) {
			_skillAttributeDes = AttributeStringSplice.getInstance().getAttributeString(this);
		}

		return _skillAttributeDes;
	}

	/**
	 * 获得没有当前学习条件的技能描述
	 * 
	 * @return
	 */
	public String getSkillAttributeDesWithoutCondition() {
		return _skillDesWithoutLearnCondition;
	}

}
